﻿import mx.utils.Delegate;
import My3D.BitmapMaterial;
import My3D.Face;
import My3D.Point3D;
import My3D.Polygon;
import My3D.UVPoint;
dynamic class My3D.ASEFile {
	public static var M_LOADED:String = "loadedAseFileAndCreatedPolygon";
	private var $lv:LoadVars;
	private var _say:Say;
	private var $url:String;
	private var $rootmc:MovieClip;
	
	private var points:Array;
	private var uvPoints:Array;
	private var faces:Array;
	private var uvFaces:Array;
	
	private var PointsObj:Object;
	private var UVPointsObj:Object;
	private var FacesObj:Object;
	private var UVFaceObj:Object;
	private var bmp:BitmapMaterial;
	
	private var polygon:Polygon;
	
	public function get PG():Polygon {
		return this.polygon;
	}
	public function Bmp():BitmapMaterial {
		return this.bmp;
	}
	/**
	 * ASEFile , create polygon from ase file.
	 * @param	fileDir ase file dir
	 * @param	rootmc bitmap material rootmc
	 */
	public function ASEFile(fileDir:String, rootmc:MovieClip) {
		if (rootmc == undefined) {
			rootmc = _root;
		}
		this.$rootmc = rootmc;
		if (fileDir == "" || fileDir == undefined) {
			trace("error file Dir of ASE file.");
			return;
		}
		this.$url = fileDir;
		var st:Array = fileDir.split("/");
		initvars(st[st.length - 1]);
		loadFile();
		AsBroadcaster.initialize(this);
	}
	private function loadFile() {
		this.$lv.load(this.$url);
		this.$lv.onLoad = Delegate.create(this, this.loadedfile);
		
		this.points = new Array();
		this.uvPoints = new Array();
		this.faces = new Array();
		this.uvFaces = new Array();
		
		this.PointsObj = new Object();
		this.UVPointsObj = new Object();
		this.FacesObj = new Object();
		this.UVFaceObj = new Object();
	}
	private function loadedfile() {
		var data:String = this.$lv.toString().split("=&onLoad")[0];
		var items:Array = unescape(data).split("*");
		for (var i = 0; i < items.length; i++) {
			var str:String = items[i].split("\r")[0];
			
			var name:String = getTileNextChar(str,0, " ");
			if (name == "MESH_VERTEX") {
				this.points.push(str);
			}
			else if (name == "MESH_FACE") {
				this.faces.push(str);
			}
			else if (name == "MESH_TVERT") {
				this.uvPoints.push(str);
			}
			else if (name == "MESH_TFACE") {
				this.uvFaces.push(str);
			} else if (name == "BITMAP") {
				trace(str);
				trace(str.split("\"")[1]);
				var bmpmc:MovieClip=this.$rootmc.createEmptyMovieClip("BMP_fromASE" + (new Date()).getTime(), this.$rootmc.getNextHighestDepth());
				this.bmp = new BitmapMaterial(bmpmc);
				this.bmp.Url = str.split("\"")[1];
				this.bmp[BitmapMaterial.M_UPDATA] = Delegate.create(this, this.loadedBMP);
				this.bmp.load();
			}
		}
		processPoints();
		processUVPoints();
		processFaces();
		processUVFaces();
		
		//processBitmapMaterial();
	}
	private function loadedBMP(bmp:BitmapMaterial) {
		//trace("loaded bmp")
		this.createPolygon();
	}
	private function createPolygon() {
		polygon = new Polygon("POLYGON" + (new Date()).getTime());
		for (var i in FacesObj) {
			var f:Face = new Face();
			var uvPA:UVPoint = new UVPoint(UVPoint(this.UVPointsObj[UVFaceObj[i].A]).U * this.bmp.width, UVPoint(this.UVPointsObj[UVFaceObj[i].A]).V * this.bmp.height);
			var uvPB:UVPoint = new UVPoint(UVPoint(this.UVPointsObj[UVFaceObj[i].B]).U * this.bmp.width, UVPoint(this.UVPointsObj[UVFaceObj[i].B]).V * this.bmp.height);
			var uvPC:UVPoint = new UVPoint(UVPoint(this.UVPointsObj[UVFaceObj[i].C]).U * this.bmp.width, UVPoint(this.UVPointsObj[UVFaceObj[i].C]).V * this.bmp.height);
			
			f.AddPoints([this.PointsObj[FacesObj[i].A], this.PointsObj[FacesObj[i].B], this.PointsObj[FacesObj[i].C]], uvPA, uvPB, uvPC);
			f.setTestureMaterial(this.bmp);
			polygon.AddFace(f);
			
		}
		this.broadcastMessage(M_LOADED, this);
		this[M_LOADED](this);
	}
	private function processBitmapMaterial() {
		
	}
	private function processPoints() {
		//MESH_VERTEX    0	0.0000	0.0000	20.0000
		var str:String = "";
		while (str=this.points.shift().toString()) {
			str = str.substring(11);
			var datas:Array = str.split("\t");
			var id:Number = Number(datas[0]);
			this.PointsObj[id] = new Point3D(Number(datas[1]), Number(datas[2]), Number(datas[3]));
			
		}
		//Debug.trace(this.PointsObj)
	}
	private function processUVPoints() {
		//MESH_TVERT 0	0.0000	1.0000	0.0000
		var str:String = "";
		while (str=this.uvPoints.shift().toString()) {
			str = str.substring(10);
			var datas:Array = str.split("\t");
			var id:Number = Number(datas[0]);
			this.UVPointsObj[id] = new UVPoint(Number(datas[1]), Number(datas[2]));
		}
		//Debug.trace(this.PointsObj);
	}
	private function processFaces() {
		//MESH_FACE    0:    A:    0 B:    1 C:    2 AB:    1 BC:    1 CA:    1	 
		var str:String = "";
		while (str=this.faces.shift().toString()) {
			str = str.substring(9);
			var id:Number = Number(str.substring(0, 5));
			str = str.substring(12);
			var A:Number = Number(str.substring(0, 5));
			str = str.substring(8);
			var B:Number = Number(str.substring(0, 5));
			str = str.substring(8);
			var C:Number = Number(str.substring(0, 5));
			//trace(id + ": a=" + A + " b=" + B + " c=" + C);
			this.FacesObj[id] = ( { A:A, B:B, C:C } );
		}
	}
	private function processUVFaces() {
		//MESH_TFACE 0	0	17	18
		var str:String = "";
		while (str=this.uvFaces.shift().toString()) {
			str = str.substring(10);
			var datas:Array = str.split("\t");
			var id:Number = Number(datas[0]);
			this.UVFaceObj[id] = ( { A:Number(datas[1]), B:Number(datas[2]), C:Number(datas[3]) } );
		}
		//Debug.trace(this.PointsObj);
	}
	
	private function getTileNextChar(str:String, startindex:Number, car:String):String {
		if (startindex == undefined) {
			startindex = 0;
		}
		if (str.length <= 0) return "";
		var s:String = "";
		var cr:String = "";
		var i = startindex;
		while ((cr=str.charAt(i++))!=car) {
			s += cr;
			if (i == str.length) break;
		}
		return s;
	}
	private function initvars(id:String) {
		_say = new Say("ASEFile[" + id + "]");
		this[Say.M_SAY] = this.sayfun;
		this._say.addListener(this);
		this.$lv = new LoadVars();
	}
	private function sayfun(o) {
		trace(o);
	}
}